Préparation de l'espace de travail (définition du chemin des packages) :
In [1]:
%matplotlib inline
import sys
sys.path.append(r'C:\Users\ntotaro\Documents\TOOLBOX\PYTHON')
import numpy as np #import des fonctions mathématiques du package numpy
Les objets "cartesianLine" permette de faire des traitements (bruit, transformée de Fourier spatiale, zero-padding, affichage) sur des données d'une ligne régulière. Les objets "lineGridPoints2D" et "lineGridPoints3D" héritent de l'objet "cartesianLine". Ils permettent de repérer la ligne régulière dans un espace 2D ou 3D
Pour utiliser cet objet il faut déjà l'importer
In [2]:
from SiRoCo_Project.tools.classCartesianLine import cartesianLine
Ensuite, il faut initialiser un objet "cartesianLine"
In [3]:
ligne1 = cartesianLine()
A ce niveau là, l'objet "ligne1" est vide (pas de coordonées, pas de données). On peut associer des points et des données de plusieurs manières différentes : soit d'un seul bloc soit par ajouts successifs.
Soit des données disponible sous la forme de listes ou de vecteur (numpy array). Ces données peuvent être ajoutées directement à l'objet cartesianLine d'un seul bloc du moment qu'elles sont de mêmes dimension (points et valeurs). Prenons par exemple les données suivantes, associées à une liste de points:
In [4]:
x = np.linspace(0.0,1.0,100) # liste de 20 valeurs de x entre 0. et 1.
print("valeurs de x : " + str(x))
v = np.sin(2*np.pi/0.6*x)
print("valeurs de la fonction : "+str(v))
L'ensemble des données étant créé, on peut maintenant les affecter à l'objet "ligne1" :
In [5]:
ligne1.setX(x)
ligne1.setData(v)
print(ligne1.data1.shape)
In [6]:
#ligne1.delete() # efface les données précédemment affectées
x = np.linspace(0.0,1.0,100)
#for valx in x:
# valv = np.sin(2*np.pi/0.6*valx)
# ligne1.append(valx, valv)
#print(ligne1.data1.shape)
Dernière variante, il est possible d'affecter les points et les valeurs successivement mais séparément. Dans l'exemple suivant, les points sont affectés d'un bloc mais les données successivement :
In [7]:
#ligne1.delete() # efface les données précédemment affectées
x = np.linspace(0.0,1.0,100)
#ligne1.setX(x)
#for valx in x:
# valv = np.sin(2*np.pi/0.6*valx)
# ligne1.appendDataOnly(valv)
In [8]:
ligne1.plot()
In [9]:
ligne1.noisify(SNR = 20) #ajout d'un bruit d'un SNR de 20dB (sur la partie réelle et sur la partie imaginaire)
ligne1.plot() #la fonction plot n'affiche qu'une seule courbe si les données sont réelles, 2 si elles sont complexes
Des fenêtrages des donées sont possibles. Pour l'instant les fenêtres "rectangular" et "hanning" sont disponibles. Le fenêtrage de type "hanning" se fait sur toute la fenêtre (quelles que soient les valeurs de x). Le filtrage 'rectangular' applique un filtre passe-bande (0 ou 1) entre les valeurs -cuttingv et +cuttingv (valeur de coupure)
In [10]:
ligne1.windowing(wtype = 'hanning')# applique une fenêtre de type hanning aux données
#ligne1.windowing(wtype = 'rectangular', cuttingv = 0.6)# applique un filtre passe-bande entre -0.6 et +0.6
ligne1.plot()
In [11]:
ligne1.padding(coeff = 1)# ajoute autant de 0 avant et après les données qui n'y avait de valeurs de données
ligne1.plot()
In [12]:
ligne1.kspace()
ligne1.plot()
In [13]:
ligne1.kspace_inverse()
ligne1.plot()
In [14]:
ligne1.resetProcessing()
ligne1.plot()
print(ligne1.data1.shape)
Les objets de types cartesianLine peuvent s'ajouter, se soustraire, se multiplier, se diviser entre eux pourvu qu'ils soient de mêmes dimensions. Le résultat de ce calcul est de type cartesianLine (évidemment, toutes les méthodes sont héritées). Par exemple, créons un nouvel objet "ligne2" :
In [15]:
v2 = np.cos(2*np.pi/0.6*x)
ligne2 = cartesianLine()
ligne2.setX(x)
ligne2.setData(v2)
ligne2.plot()
On peut additionner les deux objets :
In [16]:
somme = ligne1 + ligne2
somme.plot()
les soustraire :
In [17]:
reste = ligne1 - ligne2
reste.plot()
les multiplier :
In [18]:
mult = ligne1 * ligne2
mult.plot()
et les diviser :
In [19]:
divi = ligne1 / ligne2 # attention à la division par 0
divi.plot()
et faire une combinaison de tout ça
In [20]:
calc = ligne1*2 + ligne2/5 * ligne1
calc.plot()
In [21]:
vectx = calc.getX()
val = calc.getData()
Ces données sont des numpy arrays. On peut récupérer d'autres informations comme le type de données (scalaire ou vectorielle, méthode getDataType), l'espace des données (géométrique ou espace des nombres d'ondes, méthode getDataSpace) la longueur de la ligne (méthode length) :
In [22]:
t = ligne1.getDataType() # renvoie "scalar" ou "vector"
s = ligne1.getDataSpace() # renvoie "space" ou "kspace"
longueur = ligne1.length()
print(t)
print(s)
print(longueur)
In [23]:
vx = np.cos(3*x)
vy = np.cos(2*x)
vz = np.sin(3*x)
# Premiere methode -> d'un bloc
lignevect1 = cartesianLine(dataType='vector')
lignevect1.setX(x)
lignevect1.setData([vx, vy, vz]) #les données peuvent être une liste de 3 vecteurs ou une matrice (np.array)
# Deuxième méthode -> à l'initialisation
lignevect2 = cartesianLine(dataType='vector', x = x, datax = vx, datay = vy, dataz = vz)
# Troisième méthode -> au fur et à mesure
lignevect3 = cartesianLine(dataType='vector')
for nn, xx in enumerate(x):
lignevect3.append(xx, [vx[nn], vy[nn], vz[nn]])
# ou
# lignevect3.appendXOnly(xx)
# lignevect3.appendDataOnly([vx[nn], vy[nn], vz[nn]])
lignevect1.plot()
Ces deux objets, très similaires, héritent tous les deux de toutes les méthodes précédemment exposées pour les object cartesianLine. Ces objets représentent des lignes de points régulièrement espacés dans l'espace 2D ou 3D. Les classes lineGridPoints2D et lineGridPoints3D s'importe par :
In [24]:
from SiRoCo_Project.tools.classCartesianLine import lineGridPoints2D, lineGridPoints3D
On déclare ensuite des objets (ici une ligne l2d et une ligne l3d)
In [25]:
l2d = lineGridPoints2D(x0=0.1, y0=0.2, L=1., d=0.01, theta=0., dataType='scalar') #création d'une ligne de points associée à des données scalaires dont le point initial est en (x0,y0), d'une longueur L, avec des points espacés de d et faisant un angle theta avec l'axe x
l3d = lineGridPoints3D(x0=0.1, y0=0.2, z0=0.1, L=1., d=0.01, theta=0., phi=0., dataType='vector') #création d'une ligne de points associée à des données vectorielles dont le point initial est en (x0,y0,z0), d'une longueur L, avec des points espacés de d et faisant un angle theta avec l'axe x et un angle phi
On peut ensuite associer des données aux points dont les coordonnées ont été calculées dans le repère 2D ou 3D (contrairement aux cartesianLine on ne doit pas affecter de valeurs de x, elles sont calculées en fonction des paramètres entrés). Les données peuvent être affectées par les méthodes (appendDataOnly) ou (setData) !!les données doivent être compatibles avec le nombre de points définis!!.
Exemple lineGridPoints2D : Prenons l'exemple d'une plaque appuyée de dimension Lx et Lz. On souhait récupérer la déformée modale du mode (m=3, n=2) sur une ligne suivant la diagonale de la plaque. L'exemple suivant résoud ce problème
In [26]:
m=3
n=2
Lx, Ly = 0.7, 1.
modeLine = lineGridPoints2D(x0=0., y0=0., L=np.sqrt(Lx**2+Ly**2), d=0.01, theta=np.arctan(Lx/Ly), dataType='scalar')
for xc, yc in zip(modeLine.getX2D(), modeLine.getY2D()):
defmn = np.sin(m*np.pi/Lx*xc)*np.sin(n*np.pi/Ly*yc)
modeLine.appendDataOnly(defmn)
modeLine.setXLabel('Position sur la diagonale (m)')
modeLine.setDataLabel('Mode (' + str(m) + ',' + str(n) + ')')
modeLine.plot()
Exemple lineGridPoints3D : Soit une cavité de dimensions Lx, Ly, Lz. On souhaite tracer le mode (4,5,2) suivant une ligne parralèlle à z et démarrant au point (0.2,0.3,0.)
In [27]:
m = 4
n = 5
p = 2
Lx, Ly, Lz = 0.7, 1., 1.2
modeLine2 = lineGridPoints3D(x0=0.2, y0=0.3, z0=0., L=Lz, d=0.01, theta=0, phi=-np.pi/2, dataType='scalar')
for xc, yc, zc in zip(modeLine2.getX3D(), modeLine2.getY3D(), modeLine2.getZ3D()):
defmnp = np.cos(m*np.pi/Lx*xc)*np.cos(n*np.pi/Ly*yc)*np.cos(p*np.pi/Lz*zc)
modeLine2.appendDataOnly(defmnp)
modeLine2.setXLabel('Position selon z (m)')
modeLine2.setDataLabel('Mode (' + str(m) + ',' + str(n) + ',' + str(p) + ')')
modeLine2.plot()